package k8s

import (
	"context"

	corev1 "k8s.io/api/core/v1"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	core "k8s.io/client-go/kubernetes/typed/core/v1"
)

const (
	EventBusNodeChangeKey = "eventbus:k8s:node:change"
)

func NewNode(cli *kubernetes.Clientset) *Node {
	return &Node{
		core: cli.CoreV1(),
	}
}

type Node struct {
	sourceWatcher[*corev1.Node]

	core core.CoreV1Interface

	didWatch bool
	watchCtx context.Context
}

func SubScribeNodeChange(cb ...SourceWatchCallback[*corev1.Node]) error {
	return AddSubscribers(EventBusNodeChangeKey, cb...)
}

func (s *Node) Watch(ctx context.Context, cb ...SourceWatchCallback[*corev1.Node]) error {
	if s.didWatch {
		return SubScribeNodeChange(cb...)
	}
	defer func() { s.didWatch = true }()

	s.watchCtx = ctx
	chain, err := s.core.Nodes().Watch(ctx, v1.ListOptions{Watch: true})
	if err != nil {
		return err
	}
	s.GoWatch(ctx, EventBusNodeChangeKey, chain, cb...)
	return nil
}

func (s *Node) StopWatch(ctx context.Context) {
	if ctx != nil {
		ctx.Done()
	}
	if s.watchCtx != nil && s.watchCtx != ctx {
		s.watchCtx.Done()
	}
}

// 获取节点列表
func (s *Node) GetNodes(ctx context.Context, req *v1.ListOptions) (*corev1.NodeList, error) {
	return s.core.Nodes().List(ctx, *req)
}

// 获取节点详情
func (s *Node) GetNodeDetails(ctx context.Context, name string) (*corev1.Node, error) {
	return s.core.Nodes().Get(ctx, name, v1.GetOptions{})
}

// 删除节点
func (s *Node) DeleteNode(ctx context.Context, name string) error {
	return s.core.Nodes().Delete(ctx, name, v1.DeleteOptions{})
}

// 更新节点
func (s *Node) UpdateNode(ctx context.Context, node *corev1.Node) (*corev1.Node, error) {
	return s.core.Nodes().Update(ctx, node, v1.UpdateOptions{})
}

// 创建节点
func (s *Node) CreateNode(ctx context.Context, node *corev1.Node) (*corev1.Node, error) {
	return s.core.Nodes().Create(ctx, node, v1.CreateOptions{})
}
